home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
tool
/
dprint
/
fselect.c
< prev
next >
Wrap
Text File
|
1994-08-11
|
8KB
|
373 lines
/*
ファイルセレクタルーチン
Copyleft 1994 Delmonta
このソースファイルは自由に再利用してかまいません。
*/
#include<stdio.h>
#include<string.h>
#include<jstring.h>
#include<ctype.h>
#include<stdlib.h>
#include<dos.h>
#include<direct.h>
#include<setjmp.h>
#include"dprint.h"
/*-------------------------------マクロ定義----------------------------------*/
#define ONELINE 5 /* 1行に表示するファイルの数 */
#define LINENUM 5 /* ファイル表示部の行数 */
#define STARTPOS SYSLINE_START /* ファイルセレクタエィンドウ表示開始行 */
#define SPACENUM ((78-12*ONELINE)/(ONELINE-1))
/* 行中のファイルの間のスペースの数 */
/*--------------------------------型と変数-----------------------------------*/
static struct DIRCHAIN
{
char name[13];
int attr;
unsigned date;
unsigned time;
long size;
struct DIRCHAIN *prev;
struct DIRCHAIN *next;
} **Dir = NULL;
static char Path[64];
static int Drive;
static int Offset,Pos;
static int Dirnum;
static jmp_buf Jmp_buf;
/*--------------------------ディレクトリ検索ルーチン-------------------------*/
static struct DIRCHAIN *opndir(char *path, char attr)
{
char *chp;
static struct find_t fib;
struct DIRCHAIN *dirtop;
struct DIRCHAIN *dir;
static char buf[FILENAME_MAX];
strncpy(buf, path, FILENAME_MAX - 1);
chp = strchr(buf,'\0') -1;
if (*chp==':' || *chp=='\\')
strncat(buf, "*.*", FILENAME_MAX - 1);
if (_dos_findfirst(buf, attr, &fib))
return NULL;
if ((dir = dp_malloc(sizeof(struct DIRCHAIN))) == NULL)
return NULL;
dirtop = dir;
dir->prev = NULL;
strcpy(dir->name, fib.name);
dir->attr = fib.attrib;
dir->time = fib.wr_time;
dir->date = fib.wr_date;
dir->size = fib.size;
dir->next = NULL;
while (_dos_findnext(&fib) == 0)
{
if ((dir->next = dp_malloc(sizeof(struct DIRCHAIN))) == NULL)
return dirtop;
dir->next->prev = dir;
dir = dir->next;
strcpy(dir->name, fib.name);
dir->attr = fib.attrib;
dir->time = fib.wr_time;
dir->date = fib.wr_date;
dir->size = fib.size;
dir->next = NULL;
}
return dirtop;
}
/*---------------指定されたディレクトリを検索して配列に展開------------------*/
static void dirfree(void)
{
int i;
for (i=0 ; i<Dirnum ; i++)
free(Dir[i]);
free(Dir);
Dir = NULL;
}
static int cmp(struct DIRCHAIN **a,struct DIRCHAIN **b)
{
int p = ((*a)->attr & _A_SUBDIR);
int q = ((*b)->attr & _A_SUBDIR);
if (p && !q) return -1; /* ディレクトリはそれ以外の */
else if (!p && q) return 1; /* ファイルより優先 */
p = ((*a)->name[0]=='.');
q = ((*b)->name[0]=='.');
if (p && !q) return -1; /* 先頭の"." ".." 対策 */
else if (!p && q) return 1;
else if (p && q)
{
if ((*a)->name[1]=='.') return 1;
else return 0;
}
else
return strcmp((*a)->name,(*b)->name);
}
static void scan(void)
{
struct DIRCHAIN *d1,*d2;
int i;
if (Dir!=NULL)
dirfree();
Dirnum = 0;
d1 = opndir(Path,_A_SUBDIR);
if (d1==NULL) /* ルートに何もない場合を考慮 */
{
d1 = dp_malloc(sizeof(struct DIRCHAIN));
if (d1==NULL)
longjmp(Jmp_buf,1);
d1->name[0] = '.';
d1->name[1] = '\0';
d1->attr = _A_SUBDIR;
d1->next = NULL;
}
for (d2=d1 ; d2!=NULL ; d2=d2->next)
Dirnum++;
Dir = dp_malloc(sizeof(struct DIRCHAIN *)*Dirnum);
if (Dir==NULL)
longjmp(Jmp_buf,1);
for (d2=d1,i=0 ; i<Dirnum ; i++,d2=d2->next)
Dir[i] = d2;
qsort(Dir,Dirnum,sizeof(Dir[0]),(int(*)(const void*,const void*))cmp);
}
/*--------------------------------画面の初期化-------------------------------*/
static void openwindow(void)
{
printf("\033[%d;1f"
"─────────────────ファイル選択─────────────────"
"\033[%d;1f"
"────────────────────────────────────────"
"ファイル名 \n"
"────────────────────────────────────────"
"ドライブ変更:[TAB]",STARTPOS,STARTPOS+LINENUM+1);
}
static void closewindow(void)
{
int i;
dirfree();
printf("\033[%d;1f",STARTPOS);
for (i=0 ; i<=LINENUM+4 ; i++)
printf("\033[2K\n");
}
/*------------------------画面へのファイル名の表示---------------------------*/
void putfile(int pos)
{
printf("\033[%d;%df",(pos-Offset)/ONELINE+STARTPOS+1,
3+pos%ONELINE*(12+SPACENUM));
if (pos>=Dirnum)
{
printf("%14s","");
return;
}
if (Dir[pos]->attr & _A_SUBDIR) putchar('<');
else putchar(' ');
if (Pos==pos)
printf("\033[7m");
printf("%-12s\033[0m",Dir[pos]->name);
if (Dir[pos]->attr & _A_SUBDIR) putchar('>');
else putchar(' ');
if (Pos==pos)
printf("\033[%d;%df\033[33m%s%s\033[0K\033[37m",
STARTPOS+LINENUM+2,12,Path,Dir[pos]->name);
}
void putpage()
{
int i;
for (i=0 ; i<ONELINE*LINENUM ; i++)
putfile(Offset+i);
}
/*-----------------------------ドライブの変更--------------------------------*/
bool isdriveexist(char drv) /* drvは大文字と仮定 */
{
int a,b;
drv = drv-'A'+1;
_dos_getdrive(&a);
_dos_setdrive(drv,&b);
_dos_getdrive(&b);
if (b!=drv)
return FALSE;
_dos_setdrive(a,&b);
return TRUE;
}
void get_current_directory(char drv,char *path)
{
union REGS reg;
reg.h.ah = 0x47;
reg.h.dl = drv-'A'+1;
reg.x.si = (unsigned)path;
intdos(®,®);
}
void input_driveno(void)
{
char c;
printf("\033[%d;1f\033[2Kドライブ名:",STARTPOS+LINENUM+2);
rep:
c = dp_getch();
if (!isalpha((unsigned char)c) || !isdriveexist(c=toupper(c)))
{
putchar('\a');
goto rep;
}
Path[0] = c;
Path[1] = ':';
Path[2] = '\\';
get_current_directory(c,Path+3);
if (Path[3]!='\0')
strcat(Path,"\\");
printf("\033[%d;1f\033[2Kファイル名 ",STARTPOS+LINENUM+2);
}
/*-------------------------------メインルーチン------------------------------*/
FILE *fileselector(char *mode,char *name)
{
char c;
if (setjmp(Jmp_buf)==1)
return NULL;
getcwd(Path,sizeof(Path)-1);
if (strchr(Path,'\0')[-1]!='\\')
strcat(Path,"\\");
openwindow();
restart:
scan();
Offset = Pos = 0;
putpage();
keyrep:
c = dp_getch();
if (c==EXTKEY_H) /* 特殊キーは捨てる */
{
dp_getch();
goto keyrep;
}
if (c=='\t') /* HT:ドライブの変更 */
{
input_driveno();
goto restart;
}
else if (c=='\033') /* ESC:中断 */
{
closewindow();
return NULL;
}
/* CR:ディレクトリ移動 */
else if (c=='\r' && (Dir[Pos]->attr & _A_SUBDIR))
{
if (Dir[Pos]->name[0]=='.')
{
if (Dir[Pos]->name[1]=='\0')
goto keyrep;
else
{
*jstrrchr(Path,'\\') = '\0';
jstrrchr(Path,'\\')[1] = '\0';
}
}
else /* サブディレクトリ */
{
strcat(Path,Dir[Pos]->name);
strcat(Path,"\\");
}
goto restart;
}
/* CR/文字キー:キーボードからのファイル名入力モード */
else if (c=='\r' || !iscntrl((unsigned char)c))
{
char buf[64];
strcpy(buf,Path);
if (c=='\r')
strcat(buf,Dir[Pos]->name);
else
dp_ungetch(c);
printf("\033[%d;%df",STARTPOS+LINENUM+2,12);
if (strinput(buf,sizeof(buf)))
{
FILE *fp = fopen(buf,mode);
if (fp!=NULL)
{
if (name!=NULL)
strcpy(name,buf);
closewindow();
return fp;
}
dp_errmes("ファイルがオープンできません");
}
putfile(Pos);
}
else
{
int p = Pos;
switch (c)
{
case UPKEY: if (Pos>=ONELINE) Pos-=ONELINE; break;
case DOWNKEY: if (Pos+ONELINE<Dirnum) Pos+=ONELINE; break;
case LEFTKEY: if (Pos>0) Pos--; break;
case RIGHTKEY: if (Pos+1<Dirnum) Pos++; break;
default: putchar('\a'); break;
}
if (Pos<Offset) /* 上へスクロール */
Offset-=ONELINE,putpage();
else if (Pos>=Offset+ONELINE*LINENUM) /* 下へスクロール */
Offset+=ONELINE,putpage();
else if (p!=Pos) /* 反転するファイルの変更のみ */
putfile(p),putfile(Pos);
}
goto keyrep;
}